import 'dart:convert';
import 'dart:io';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

import 'package:shared_preferences/shared_preferences.dart';

class HttpAndModelPage extends StatefulWidget {
  final Map<String, dynamic> arguments;
  HttpAndModelPage({Key key, this.arguments}) : super(key: key);

  @override
  _HttpAndModelPageState createState() => _HttpAndModelPageState();
}

class _HttpAndModelPageState extends State<HttpAndModelPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('HttpAndModelPage'),
      ),
      body: ListView(
        children: <Widget>[
          ListTile(
            title: Text('HttpClient Uri HttpClientRequest HttpClientResponse'),
            subtitle: Text('''
- async 异步方法;
- await 等待异步方法执行完成;'''),
            onTap: () {
              fetchData() async {
                final hc = HttpClient();
                final uri = Uri.http('news-at.zhihu.com', '/api/3/stories/latest');
                final req = await hc.getUrl(uri);
                final res = await req.close();
                print('fetchData 3');
                return await res.transform(utf8.decoder).join();
              }

              print('fetchData 1');
              final data = fetchData();
              data.then((value) {
                print(value);
              }).whenComplete(() {
                print('done');
              });

              print('fetchData 2');
              print(data);
            },
          ),
          Divider(height: 1.0),
          ListTile(
            title: Text('Map jsonString model 互转'),
            onTap: () {
              // Map -> jsonString
              final Map<String, dynamic> map = {
                'title': 'coder',
                'id': '23232324',
              };
              final jsonString = json.encode(map);
              print(jsonString);

              // jsonString -> Map
              final m = json.decode(jsonString);
              print(m['title']);

              // map -> model
              final model = BookModel.fromJson(map);
              print(model.id);

              // model -> map
              final map1 = model.toMap();
              print(map1['title']);
            },
          ),
          Divider(height: 1.0),
          ListTile(
            title: Text('Future delayed timeout'),
            onTap: () {
              testFuture() async {
                // delayed
                int result = await Future.delayed(Duration(microseconds: 2000), () {
                  return Future.value(123);
                });

                print('t3: ' + DateTime.now().toString());
                print(result);
              }

              print('t1: ' + DateTime.now().toString());
              testFuture();
              print('t2: ' + DateTime.now().toString());

              // timeout
              Future.delayed(Duration(seconds: 3), () {
                return 'coder';
              }).timeout(Duration(seconds: 2)).then((t) {
                print(t); // coder
              }).catchError((e) {
                print(e); // TimeoutException after 0:00:02.000000: Future not completed
              }).whenComplete(() {
                print('Complete.');
              });
            },
          ),
          Divider(height: 1.0),
          ListTile(
            title: Text('Future then catchError whenComplete'),
            onTap: () {
              final random = Random();
              final future = Future.delayed(Duration(seconds: 1), () {
                if (random.nextBool()) {
                  return 123;
                } else {
                  throw 'boom!';
                }
              });

              future.then(print).catchError((print)).whenComplete(() {
                print('done');
              });
            },
          ),
          Divider(height: 1.0),
          ListTile(
            title: Text('http -> jsonString -> map -> model'),
            onTap: () {
              fetchBookModels().then((value) {
                value.forEach((item) {
                  print(item.title);
                });
              });
            },
          ),
          Divider(height: 1.0),
          ListTile(
            title: Text('FutureBuilder AsyncSnapshot'),
            subtitle: FutureBuilder<List<BookModel>>(
              // initialData: null,
              future: fetchBookModels(),
              // builder: (BuildContext context, AsyncSnapshot<List<BookModel>> s) {
              builder: (c, s) {
                Widget w;
                switch (s.connectionState) {
                  case ConnectionState.none:
                    {
                      w = Center(child: Text('none'));
                    }
                    break;

                  case ConnectionState.waiting:
                    {
                      w = Center(child: Text('waiting'));
                    }
                    break;

                  case ConnectionState.active:
                    {
                      w = Center(child: Text('active'));
                    }
                    break;

                  case ConnectionState.done:
                    if (s.hasError) {
                      w = Center(child: Text('hasError'));
                    } else {
                      w = Wrap(
                        spacing: 15.0,
                        runSpacing: 8.0,
                        children: s.data.map<Widget>((item) {
                          return ClipRRect(
                            // borderRadius: BorderRadius.only(topLeft: Radius.circular(3.0), topRight: Radius.circular(3.0)),
                            borderRadius: BorderRadius.all(Radius.circular(5.0)),
                            child: Container(
                              child: Text(item.title),
                              color: Colors.red,
                            ),
                          );
                          // return Container(
                          //   child: Text(item.title),
                          //   color: Colors.red,
                          // );
                        }).toList(),
                      );
                    }
                }
                return w;
              },
            ),
          ),
          Divider(height: 1.0),
          ListTile(
            title: Text('shared_preferences'),
            onTap: () {
              spTest() async {
                // 增
                final sp = await SharedPreferences.getInstance();
                sp.setInt('age', 18);

                // 查
                final a0 = sp.get('age'); // 动态类型
                print(a0);
                final a1 = sp.getInt('age');
                print(a1);

                sp.setString('name', 'Coder');
                final keys = sp.getKeys();
                print(keys);

                // 改
                sp.setInt('age', 28);
                print(sp.getInt('age'));

                // 删
                sp.remove('age');
                sp.clear();
              }

              spTest();
            },
          ),
          Divider(height: 1.0),
        ],
      ),
    );
  }

  Future<List<BookModel>> fetchBookModels<T>() async {
    final response = await http.get('https://resources.ninghao.net/demo/posts.json');
    if (response.statusCode == 200) {
      final bodyMap = json.decode(response.body);
      List<BookModel> bookModels = bodyMap['posts'].map<BookModel>((item) => BookModel.fromJson(item)).toList();
      return bookModels;
    } else {
      throw Exception('failure');
    }
  }
}

class BookModel {
  final title;
  final id;
  final author;
  final description;
  final imageUrl;

  // BookModel(this.title, this.id, this.author, this.description, this.imageUrl);

  BookModel.fromJson(Map<String, dynamic> json)
      : title = json['title'],
        id = json['id'],
        author = json['author'],
        description = json['description'],
        imageUrl = json['imageUrl'];

  toMap() => {
        'title': title,
        'id': id,
        'author': id,
        'description': id,
        'imageUrl': id,
      };
}
